package com.youzi.tunnel.client.listen;

import javax.jmdns.JmDNS;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
import javax.jmdns.ServiceListener;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class WirelessAdbScanner {

    private List<AdbDevice> discoveredDevices = new ArrayList<>();
    private CountDownLatch scanLatch;

    public static class AdbDevice {
        private String name;
        private String ip;
        private int port;
        private String type;
        private ServiceInfo serviceInfo;

        public AdbDevice(String name, String ip, int port, String type, ServiceInfo serviceInfo) {
            this.name = name;
            this.ip = ip;
            this.port = port;
            this.type = type;
            this.serviceInfo = serviceInfo;
        }

        // Getters
        public String getName() { return name; }
        public String getIp() { return ip; }
        public int getPort() { return port; }
        public String getType() { return type; }
        public ServiceInfo getServiceInfo() { return serviceInfo; }

        @Override
        public String toString() {
            return String.format("设备: %s | IP: %s | 端口: %d | 类型: %s",
                    name, ip, port, type);
        }
    }

    /**
     * 扫描局域网内的无线ADB设备
     * @param timeoutSeconds 扫描超时时间（秒）
     * @return 发现的设备列表
     */
    public List<AdbDevice> scan(int timeoutSeconds) {
        discoveredDevices.clear();
        JmDNS jmdns = null;

        try {
            // 创建JmDNS实例
            jmdns = JmDNS.create(InetAddress.getLocalHost());
            scanLatch = new CountDownLatch(1);

            System.out.println("开始扫描无线ADB设备...");
            System.out.println("扫描超时: " + timeoutSeconds + "秒");
            System.out.println("等待设备响应...\n");

            // 监听现代无线ADB服务（Android 11+）
            JmDNS finalJmdns = jmdns;
            jmdns.addServiceListener("_adb-tls-connect._tcp.local.", new ServiceListener() {
                @Override
                public void serviceAdded(ServiceEvent event) {
                    System.out.println("发现ADB服务: " + event.getName());
                    // 立即请求服务信息
                    finalJmdns.requestServiceInfo(event.getType(), event.getName(), 1000);
                }

                @Override
                public void serviceRemoved(ServiceEvent event) {
                    System.out.println("服务移除: " + event.getName());
                }

                @Override
                public void serviceResolved(ServiceEvent event) {
                    ServiceInfo serviceInfo = event.getInfo();
                    if (serviceInfo != null && serviceInfo.getHostAddresses() != null &&
                            serviceInfo.getHostAddresses().length > 0) {

                        String host = serviceInfo.getHostAddresses()[0];
                        int port = serviceInfo.getPort();
                        String name = serviceInfo.getName();

                        AdbDevice device = new AdbDevice(name, host, port,
                                "_adb-tls-connect._tcp.local.", serviceInfo);
                        discoveredDevices.add(device);

                        System.out.println("✓ 发现无线ADB设备: " + name + " - " + host + ":" + port);
                    }
                }
            });

            // 监听传统ADB调试服务
            JmDNS finalJmdns1 = jmdns;
            jmdns.addServiceListener("_adb-debug._tcp.local.", new ServiceListener() {
                @Override
                public void serviceAdded(ServiceEvent event) {
                    System.out.println("发现传统ADB服务: " + event.getName());
                    finalJmdns1.requestServiceInfo(event.getType(), event.getName(), 1000);
                }

                @Override
                public void serviceRemoved(ServiceEvent event) {
                    System.out.println("传统服务移除: " + event.getName());
                }

                @Override
                public void serviceResolved(ServiceEvent event) {
                    ServiceInfo serviceInfo = event.getInfo();
                    if (serviceInfo != null && serviceInfo.getHostAddresses() != null &&
                            serviceInfo.getHostAddresses().length > 0) {

                        String host = serviceInfo.getHostAddresses()[0];
                        int port = serviceInfo.getPort();
                        String name = serviceInfo.getName();

                        AdbDevice device = new AdbDevice(name, host, port,
                                "_adb-debug._tcp.local.", serviceInfo);
                        discoveredDevices.add(device);

                        System.out.println("✓ 发现传统ADB设备: " + name + " - " + host + ":" + port);
                    }
                }
            });

            // 等待扫描完成
            scanLatch.await(timeoutSeconds, TimeUnit.SECONDS);

        } catch (Exception e) {
            System.err.println("扫描过程中发生错误: " + e.getMessage());
            e.printStackTrace();
        } finally {
            if (jmdns != null) {
                try {
                    jmdns.close();
                } catch (Exception e) {
                    System.err.println("关闭JmDNS时出错: " + e.getMessage());
                }
            }
        }

        return new ArrayList<>(discoveredDevices);
    }

    /**
     * 格式化输出扫描结果
     */
    public void printScanResults(List<AdbDevice> devices) {
        System.out.println("                 扫描结果汇总");

        if (devices.isEmpty()) {
            System.out.println("❌ 未发现任何无线ADB设备");
            System.out.println("\n可能的原因:");
            System.out.println("1. 设备未开启无线ADB调试");
            System.out.println("2. 设备和电脑不在同一局域网");
            System.out.println("3. 防火墙阻止了mDNS广播");
            System.out.println("4. 设备不支持mDNS服务发现");
        } else {
            System.out.println("✅ 共发现 " + devices.size() + " 个ADB设备:");

            for (int i = 0; i < devices.size(); i++) {
                AdbDevice device = devices.get(i);
                System.out.printf("%d. %s\n", i + 1, device.toString());

                // 显示连接命令
                String connectCommand = String.format("  连接命令: adb connect %s:%d",
                        device.getIp(), device.getPort());
                System.out.println(connectCommand);

                if (i < devices.size() - 1) {
                    System.out.println();
                }
            }
        }
    }

    /**
     * 生成ADB连接脚本
     */
    public void generateConnectScript(List<AdbDevice> devices, String filename) {
        if (devices.isEmpty()) {
            return;
        }

        StringBuilder script = new StringBuilder();
        script.append("@echo off\n");
        script.append("echo 无线ADB设备连接脚本\n");
        script.append("echo ====================\n\n");

        for (int i = 0; i < devices.size(); i++) {
            AdbDevice device = devices.get(i);
            script.append("echo 连接设备").append(i + 1).append(": ").append(device.getName()).append("\n");
            script.append("adb connect ").append(device.getIp()).append(":").append(device.getPort()).append("\n");
            script.append("echo.\n");
        }

        script.append("echo 所有设备连接完成\n");
        script.append("adb devices\n");
        script.append("pause\n");

        try {
            java.nio.file.Files.write(
                    java.nio.file.Paths.get(filename),
                    script.toString().getBytes()
            );
            System.out.println("📜 连接脚本已生成: " + filename);
        } catch (Exception e) {
            System.err.println("生成脚本失败: " + e.getMessage());
        }
    }

    public static void main(String[] args) {
        WirelessAdbScanner scanner = new WirelessAdbScanner();

        // 设置扫描超时时间（默认10秒）
        int timeout = 10;
        if (args.length > 0) {
            try {
                timeout = Integer.parseInt(args[0]);
            } catch (NumberFormatException e) {
                System.out.println("使用默认超时时间: 10秒");
            }
        }

        // 执行扫描
        List<AdbDevice> devices = scanner.scan(timeout);

        // 输出结果
        scanner.printScanResults(devices);

        // 生成连接脚本（Windows批处理）
        if (!devices.isEmpty()) {
            scanner.generateConnectScript(devices, "connect_adb_devices.bat");
        }

        // 如果是Linux/macOS，也生成shell脚本
        if (!devices.isEmpty()) {
            StringBuilder shellScript = new StringBuilder();
            shellScript.append("#!/bin/bash\n");
            shellScript.append("echo \"无线ADB设备连接脚本\"\n");
            shellScript.append("echo \"====================\"\n\n");

            for (AdbDevice device : devices) {
                shellScript.append("echo \"连接设备: ").append(device.getName()).append("\"\n");
                shellScript.append("adb connect ").append(device.getIp()).append(":").append(device.getPort()).append("\n");
            }

            shellScript.append("\necho \"所有设备连接完成\"\n");
            shellScript.append("adb devices\n");

            try {
                java.nio.file.Files.write(
                        java.nio.file.Paths.get("connect_adb_devices.sh"),
                        shellScript.toString().getBytes()
                );
                // 设置执行权限
                new ProcessBuilder("chmod", "+x", "connect_adb_devices.sh").start();
                System.out.println("📜 Shell连接脚本已生成: connect_adb_devices.sh");
            } catch (Exception e) {
                System.err.println("生成Shell脚本失败: " + e.getMessage());
            }
        }
    }
}